package com.lanchetech.user.service.impl;


import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.fastjson.JSON;
import com.lanchetech.bean.request.WsSendToUserReq;
import com.lanchetech.bean.response.BasePageResp;
import com.lanchetech.bean.response.BaseResp;
import com.lanchetech.bean.response.ResultData;
import com.lanchetech.common.enums.*;
import com.lanchetech.common.util.HttpUtil;
import com.lanchetech.dao.MsgMapper;
import com.lanchetech.dao.MsgUserMapper;
import com.lanchetech.entity.Job;
import com.lanchetech.entity.Msg;
import com.lanchetech.entity.MsgUser;
import com.lanchetech.user.config.ReturnPayInfoVO;
import com.lanchetech.user.config.WeChatPayProperties;
import com.lanchetech.user.service.CommonService;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.util.SignUtils;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.NameValuePair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.*;

@Service
public class CommonServiceImpl implements CommonService {

    @Autowired
    WxPayService wxPayService;

    @Autowired
    WeChatPayProperties weChatPayProperties;

    @Autowired
    MsgUserMapper msgUserMapper;

    @Autowired
    MsgMapper msgMapper;

    @Value("${wx.pay.appId}")
    private String miniAppId;

    @Value("${im.url}")
    private String imUrl;


    @Override
    public ReturnPayInfoVO getReturnPayInfoVO(WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest) {
        WxPayUnifiedOrderResult wxPayUnifiedOrderResult = null;
        try {
            wxPayUnifiedOrderResult = wxPayService.unifiedOrder(wxPayUnifiedOrderRequest);
        } catch (WxPayException e) {
            e.printStackTrace();
            throw new RuntimeException("微信支付调起失败！");
        }
        boolean isMini = wxPayUnifiedOrderRequest.getAppid().equals(miniAppId);

        //组合参数构建支付
        Map<String, String> paySignInfo = new HashMap<>(5);
        String timeStamp = createTimestamp();
        String nonceStr = String.valueOf(System.currentTimeMillis());
        paySignInfo.put("appId", wxPayUnifiedOrderRequest.getAppid());
        paySignInfo.put("nonceStr", nonceStr);
        paySignInfo.put("timeStamp", timeStamp);
        paySignInfo.put("signType", "MD5");

        if (isMini) {
            paySignInfo.put("package", "prepay_id=" + wxPayUnifiedOrderResult.getPrepayId());
        } else {
            paySignInfo.put("prepayid", wxPayUnifiedOrderResult.getPrepayId());
        }

        String paySign = SignUtils.createSign(paySignInfo, "MD5", weChatPayProperties.getMchKey(), isMini ? null : new String[]{"signType"});

        //组合支付参数
        ReturnPayInfoVO returnPayInfoVO = new ReturnPayInfoVO();
        returnPayInfoVO.setAppId(wxPayUnifiedOrderRequest.getAppid());
        returnPayInfoVO.setNonceStr(nonceStr);
        returnPayInfoVO.setPaySign(paySign);
        returnPayInfoVO.setSignType("MD5");
        returnPayInfoVO.setPrepayId(wxPayUnifiedOrderResult.getPrepayId());
        returnPayInfoVO.setTimeStamp(timeStamp);

        return returnPayInfoVO;
    }

    @Override
    public String createQrcode(String content, int width, int height) throws IOException {
        if (!StringUtils.isEmpty(content)) {
            ServletOutputStream stream = null;
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            @SuppressWarnings("rawtypes")
            HashMap<EncodeHintType, Comparable> hints = new HashMap<>();
            hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
            // 指定二维码的纠错等级为中级
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
            hints.put(EncodeHintType.MARGIN, 0);
            try {
                QRCodeWriter writer = new QRCodeWriter();
                BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, width, height, hints);

                BufferedImage bufferedImage = MatrixToImageWriter.toBufferedImage(bitMatrix);
                ImageIO.write(bufferedImage, "png", os);
                Base64.Encoder base64Encoder = Base64.getEncoder();
                String image = base64Encoder.encodeToString(os.toByteArray());
                return image;
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (stream != null) {
                    stream.flush();
                    stream.close();
                }
            }
        }
        return null;
    }

    private String createTimestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }

    @Override
    public BaseResp postToIm(WsSendToUserReq req) {
        try {
            req.setImMessageType(MessageTypeEnum.LIVE.getType());
            String resp = HttpUtil.doJsonPost(JSON.toJSONString(req), imUrl + "/api/websocket/sendToUser");
            return JSON.parseObject(resp, BaseResp.class);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new BaseResp(ResultCode.FAIL);
    }


    @Override
    public ResultData<MsgUser> getPlatformMsgUser(Long msgUserId) {
        // 获取商家正在服务中的客服
        List<MsgUser> list = msgUserMapper.findAllByRoleAndStatusAndDeleted(MsgUserRoleEnum.ADMIN.getRole(), MsgUserStatusEnum.IN_SERVICE.getStatus(), DeletedEnum.DEFAULT.getStatus());

        // 获取嗨跑商家正在服务中的客服
        List<MsgUser> list2 = msgUserMapper.findAllByTenantIdAndStatusAndDeleted(1L, MsgUserStatusEnum.IN_SERVICE.getStatus(), DeletedEnum.DEFAULT.getStatus());
        list.addAll(list2);

        if (!CollectionUtils.isEmpty(list)) {

            // 获取最近1次沟通的消息
            Msg msg = msgMapper.findOneLastByPlatformAndFromId(msgUserId);

            // 如果沟通过，并且还在3天内
            if (msg != null && msg.getCreatedAt().getTime() + 3 * 86400 * 1000 > System.currentTimeMillis()) {
                Optional<MsgUser> msgUserOptional = list.parallelStream().filter(s -> s.getId().equals(msg.getToId())).findFirst();
                // 如果在线
                if (msgUserOptional.isPresent()) {
                    MsgUser msgUser = msgUserOptional.get();
                    msgUser.setPassword(null);
                    return new ResultData<>(msgUser);
                }
            }

            // 随机选择1个客服
            Random r = new Random();
            MsgUser msgUser = list.get(r.nextInt(list.size()));
            msgUser.setPassword(null);
            return new ResultData<>(msgUser);
        }
        return new ResultData<>(null);
    }

    @Override
    public ResultData<MsgUser> getNormalMsgUser(Long userId) {
        return new ResultData<>(msgUserMapper.findOneByRelateIdAndRole(userId, MsgUserRoleEnum.USER.getRole()));
    }

}